﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Applee.FractCommon
{
    public class MathUtils
    {
        public static float Epsilon = 0.0001F;
        public static PointF AddPoint(PointF point01, PointF point)
        {
            return new PointF(point01.X + point.X, point01.Y + point.Y);
        }

        public static PointF Midpoint(PointF point01, PointF point)
        {
            return new PointF((point01.X + point.X) * 0.5F, (point01.Y + point.Y) * 0.5F);
        }

        public static PointF ExtendPoint(PointF pointBase, PointF point, float fLength)
        {
            float fAngle = (float)AngleFromP2P(pointBase, point);
            if(IsEqual(fAngle, 0))
            {
                return new PointF(point.X + fLength, point.Y);
            }
            else if (IsEqual(fAngle, (float)Math.PI))
            {
                return new PointF(point.X - fLength, point.Y);
            }
            else if (IsEqual(fAngle, (float)Math.PI * 0.5F))
            {
                return new PointF(point.X, point.Y + fLength);
            }
            else if (IsEqual(fAngle, -(float)Math.PI * 0.5F))
            {
                return new PointF(point.X, point.Y - fLength);
            }
            else
            {
                return new PointF(point.X + (float)Math.Cos(fAngle) * fLength, point.Y + (float)Math.Sin(fAngle));
            }
        }

        public static PointF RotatePoint(PointF pointBase, PointF point, float fa)
        {
            float fAngle = (float)(fa * Math.PI / 180);
            return RotatePointRad(pointBase, point, fAngle);
        }

        public static PointF RotatePointRad(PointF pointBase, PointF point, float fAngle)
        {
            PointF resPoint = new PointF();
            resPoint.X = pointBase.X + (point.X - pointBase.X) * (float)Math.Cos(fAngle) - (point.Y - pointBase.Y) * (float)Math.Sin(fAngle);
            resPoint.Y = pointBase.Y + (point.Y - pointBase.Y) * (float)Math.Cos(fAngle) + (point.X - pointBase.X) * (float)Math.Sin(fAngle);
            return resPoint;
        }

        public static float AngleFromP2P(PointF pointBase, PointF pt1, PointF pt2)
        {
            if (IsNullPoint(pt1) || IsNullPoint(pt2))
                return 0;

            double d1 = AngleFromP2P(pt2, pointBase);
            double d2 = AngleFromP2P(pt1, pointBase);

            return (float)(d1 - d2);
        }

        public static double AngleFromP2P(PointF pointBase, PointF pt1)
        {
            if (IsNullPoint(pt1))
                return 0;

            if (IsEqual(pt1.X, pointBase.X))
            {
                if (pointBase.Y - pt1.Y < 0)
                {
                    return Math.PI * 0.5F;
                }
                else
                {
                    return -Math.PI * 0.5F;
                }
            }
            else if(IsEqual(pt1.Y, pointBase.Y))
            {
                if (pointBase.X - pt1.X < 0)
                {
                    return 0;
                }
                else
                {
                    return Math.PI;
                }
            }
            else
            {
                return Math.Atan((pt1.Y - pointBase.Y) / (pt1.X - pointBase.X));
            }
        }

        private static bool IsNullPoint(PointF pt)
        {
            return IsEqual(pt.X, 0) && IsEqual(pt.Y, 0);
        }

        public static float Distance(PointF p1, PointF p2)
        {
            return (float)Math.Sqrt((p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y));
        }

        public static bool IsEqual(float f1, float f2)
        {
            return Math.Abs(f1 - f2) < Epsilon;
        }

        //以第一个点为基点移动到PointTo
        public static PointF[] MovePoints(PointF[] points, PointF pointBase, PointF pointTo)
        {
            if (points == null)
                return null;

            float x = pointTo.X - pointBase.X;
            float y = pointTo.Y - pointBase.Y;

            for (int i = 0; i < points.Length; i++ )
                points[i] = new PointF(points[i].X + x, points[i].Y + y);

            return points;
        }

        //return true-width,false-height
        public static bool CalcAdaptiveLength(Size viewSize, SizeF shapeSize, ref float fLength)
        {
            float fBaseEdge = viewSize.Height;

            //H=Rcos36+R
            //W=2Rcos18
            float frShape = shapeSize.Width * 1.0F / shapeSize.Height;

            //view
            float frView = viewSize.Width * 1.0F / viewSize.Height;
            if (frView < frShape)
            {
                fLength = viewSize.Width;
                return true;
            }
            else
            {
                fLength = viewSize.Height;
                return false;
            }

            //
        }

        public static bool IsEqual(PointF pt1, PointF pt2)
        {
            return IsEqual(pt1.X, pt2.X) && IsEqual(pt1.Y, pt2.Y);
        }
    }
}
